import { Controller, Get, Post, Body, Param, Put, Delete, Req, Res, QueryParams } from 'routing-controllers';
import { Container } from 'typedi';
import { MenuService } from '@services/menu.service';
import { CreateMenuDto, MenuPageDto, UpdateMenuDto } from '@/dtos';
import { Log, LogOperation } from '@decorators/logs.decorators';
import { Request, Response } from 'express';
import { ApiResponseBuilder } from '@utils/api-response-builder';
import { OpenAPI } from 'routing-controllers-openapi';
import { RequestWithUser } from '@/interfaces';
import { RequiredPerm } from '@decorators/perm.decorator';

@Controller('/menus')
export class MenuController {
  private menu = Container.get(MenuService);

  @Get('/list/all')
  @RequiredPerm('menus:list:all')
  @OpenAPI({ summary: '超级管理员获取菜单所有信息' })
  async getMenuTree(@Req() req: RequestWithUser, @Res() res: Response) {
    const tree = await this.menu.getMenuTree();
    return new ApiResponseBuilder(req, res).success(tree);
  }

  @Get('/list')
  @OpenAPI({ summary: '获取当前用户可见菜单树（目录 + 菜单）' })
  async getTree(@Req() req: RequestWithUser, @Res() res: Response) {
    const roleCodes = req.user.roles.map(role => role.code);
    const tree = await this.menu.getMenuTreeByRoles(roleCodes);
    return new ApiResponseBuilder(req, res).success(tree);
  }

  @Get('/perms/button')
  @OpenAPI({ summary: '获取当前用户按钮权限码列表' })
  async getButtonPerms(@Req() req: RequestWithUser, @Res() res: Response) {
    const roleCodes = req.user.roles.map(role => role.code);
    const codes = await this.menu.getButtonPermCodesByRoles(roleCodes);
    return new ApiResponseBuilder(req, res).success(codes);
  }

  @Get('/perms/api')
  @OpenAPI({ summary: '获取当前用户 API 权限码列表' })
  async getApiPerms(@Req() req: RequestWithUser, @Res() res: Response) {
    const roleCodes = req.user.roles.map(role => role.code);
    const codes = await this.menu.getApiPermCodesByRoles(roleCodes);
    return new ApiResponseBuilder(req, res).success(codes);
  }

  @Get('/perms/all')
  @OpenAPI({ summary: '获取当前用户全部权限码' })
  async getAllPerms(@Req() req: RequestWithUser, @Res() res: Response) {
    const roleCodes = req.user.roles.map(role => role.code);
    const [button, api] = await Promise.all([this.menu.getButtonPermCodesByRoles(roleCodes), this.menu.getApiPermCodesByRoles(roleCodes)]);
    return new ApiResponseBuilder(req, res).success({ button, api });
  }

  @Get('/page')
  @RequiredPerm('menus:page')
  @OpenAPI({ summary: '菜单分页列表' })
  async findAll(@Req() req: Request, @Res() res: Response, @QueryParams() pageDto: MenuPageDto) {
    const { list, total } = await this.menu.findAll(pageDto);
    return new ApiResponseBuilder(req, res).paginate(list, total, pageDto.pageNum || 1, pageDto.pageSize || 20);
  }

  @Get('/:id')
  @RequiredPerm('menus:detail')
  @OpenAPI({ summary: '菜单详情' })
  async findOne(@Req() req: Request, @Res() res: Response, @Param('id') id: number) {
    const data = await this.menu.findOne(id);
    return new ApiResponseBuilder(req, res).success(data);
  }

  @Post('/create')
  @RequiredPerm('menus:create')
  @OpenAPI({ summary: '创建菜单' })
  @Log({ bizType: 'menu', operation: LogOperation.CREATE, bizId: (req: { user: { id: string } }) => `menu:create:${req?.user?.id ?? ''}` })
  async create(@Req() req: Request, @Res() res: Response, @Body() dto: CreateMenuDto) {
    await this.menu.create(dto);
    return new ApiResponseBuilder(req, res).success();
  }

  @Put('/update/:id')
  @RequiredPerm('menus:update')
  @OpenAPI({ summary: '更新菜单' })
  @Log({ bizType: 'menu', operation: LogOperation.UPDATE, bizId: (req: { user: { id: string } }) => `menu:update:${req?.user?.id ?? ''}` })
  async update(@Req() req: Request, @Res() res: Response, @Param('id') id: number, @Body() dto: UpdateMenuDto) {
    await this.menu.update(id, dto);
    return new ApiResponseBuilder(req, res).success();
  }

  @Delete('/delete/:id')
  @RequiredPerm('menus:delete')
  @OpenAPI({ summary: '删除菜单' })
  @Log({ bizType: 'menu', operation: LogOperation.DELETE, bizId: (req: { user: { id: string } }) => `menu:delete:${req?.user?.id ?? ''}` })
  async remove(@Req() req: Request, @Res() res: Response, @Param('id') id: number) {
    await this.menu.remove(id);
    return new ApiResponseBuilder(req, res).success();
  }
}
